﻿using Mapster;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using My.Admin.Dto.System;
using My.Admin.Dto.User;
using My.Admin.Enum;
using My.Admin.Model;
using My.Admin.Model.System;
using My.Admin.Repository;
using My.Admin.Service.System.IService;
using My.Core.CustomException;
using My.Core.Enums;
using System.ComponentModel;

namespace My.Admin.Service.System
{
	public class SysRoleService : BaseService<SysRole>, ISysRoleService
	{
		private readonly ISysRoleMenuService _sysRoleMenuRep;
		private readonly ISysUserRoleService _sysUserRoleService;
		private readonly ISysRoleMenuService _sysRoleMenuService;
		private readonly UserManager _userManager;

		public SysRoleService(ISysRoleMenuService sysRoleMenuRep, ISysUserRoleService sysUserRoleService, ISysRoleMenuService sysRoleMenuService, UserManager userManager)
		{
			_sysRoleMenuRep = sysRoleMenuRep;
			_sysUserRoleService = sysUserRoleService;
			_sysRoleMenuService = sysRoleMenuService;
			_userManager = userManager;
		}

		/// <summary>
		/// 获取用户分页列表
		/// </summary>
		/// <param name="input"></param>
		/// <returns></returns>
		public async Task<PagedInfo<SysRole>> Page(PageRoleInput input)
		{
			int totalCount = 0;
			var lSysRole = Queryable();

			if (lSysRole == null)
			{
				input.TotalNum = 0;
				return null;
			}
			input.TotalNum = totalCount;

			lSysRole = lSysRole.Where(x => x.Name.Contains(input.Name));

			return await lSysRole.ToPageAsync(input);
		}

		/// <summary>
		/// 更新角色
		/// </summary>
		/// <param name="input"></param>
		/// <returns></returns>
		[DisplayName("更新角色")]
		public async Task UpdateRole(UpdateRoleInput input)
		{
			if (await IsAnyAsync(u => u.Name == input.Name && u.Code == input.Code && u.Id != input.Id))
				throw new CustomException(ResultCode.FAIL, "数据库操作失败", "数据已存在");

			var role = input.Adapt<SysRole>();

			await AsUpdateable(input.Adapt<SysRole>()).IgnoreColumns(true).ExecuteCommandAsync();

			await UpdateRoleMenu(input);
		}

		/// <summary>
		/// 更新角色菜单权限
		/// </summary>
		/// <param name="input"></param>
		/// <returns></returns>
		private async Task UpdateRoleMenu(AddRoleInput input)
		{
			if (input.MenuIdList == null || input.MenuIdList.Count < 1)
				return;

			// 将父节点为0的菜单排除，防止前端全选异常
			var pMenuIds = await ChangeRepository<BaseRepository<SysMenu>>().AsQueryable().Where(u => input.MenuIdList.Contains(u.Id) && u.Pid == 0).ToListAsync(u => u.Id);
			var menuIds = input.MenuIdList.Except(pMenuIds); // 差集
			await GrantMenu(new RoleMenuInput()
			{
				Id = input.Id,
				MenuIdList = menuIds.ToList()
			});
		}

		/// <summary>
		/// 授权角色菜单
		/// </summary>
		/// <param name="input"></param>
		private async Task GrantMenu(RoleMenuInput input)
		{
			await _sysRoleMenuRep.GrantRoleMenu(input);
		}

		/// <summary>
		/// 增加角色
		/// </summary>
		/// <param name="input"></param>
		/// <returns></returns>
		[DisplayName("增加角色")]
		public async Task AddRole(AddRoleInput input)
		{
			if (await IsAnyAsync(u => u.Name == input.Name && u.Code == input.Code))
				throw new CustomException(ResultCode.FAIL, "数据库操作失败", "数据已存在");

			var newRole = await AsInsertable(input.Adapt<SysRole>()).ExecuteReturnEntityAsync();
			input.Id = newRole.Id;
			await UpdateRoleMenu(input);
		}

		/// <summary>
		/// 删除角色
		/// </summary>
		/// <param name="input"></param>
		/// <returns></returns>
		[DisplayName("删除角色")]
		public async Task DeleteRole(DeleteRoleInput input)
		{
			var sysRole = await GetFirstAsync(u => u.Id == input.Id) ?? throw new CustomException(ResultCode.FAIL, "数据库操作失败", "记录不存在");
			//if (sysRole.Code == CommonConst.SysAdminRole)
			//	throw Oops.Oh(ErrorCodeEnum.D1019);

			await DeleteAsync(sysRole);

			// 级联删除用户角色数据
			await _sysUserRoleService.DeleteUserRoleByRoleId(sysRole.Id);

			// 级联删除角色菜单数据
			await _sysRoleMenuService.DeleteRoleMenuByRoleId(sysRole.Id);
		}

		/// <summary>
		/// 获取角色列表
		/// </summary>
		/// <returns></returns>
		public async Task<List<RoleOutput>> GetList()
		{
			// 当前用户已拥有的角色集合
			var roleIdList = _userManager.SuperAdmin ? null : await _sysUserRoleService.GetUserRoleIdList(_userManager.UserId);
			return await AsQueryable()
				.WhereIF(roleIdList != null, u => u.CreateUserId == _userManager.UserId || roleIdList.Contains(u.Id)) // 若非超管，则只显示自己创建和已拥有的角色
				.OrderBy(u => u.OrderNo).Select<RoleOutput>().ToListAsync();
		}
	}
}
